package com.yungu.swift.assets.driver.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alicp.jetcache.anno.Cached;
import com.yungu.swift.assets.driver.dao.CarMapper;
import com.yungu.swift.assets.driver.dao.CarModelMapper;
import com.yungu.swift.assets.driver.dao.CarModelValuationMapper;
import com.yungu.swift.assets.driver.model.dto.CarModelDto;
import com.yungu.swift.assets.driver.model.dto.CarModelValuationDto;
import com.yungu.swift.assets.driver.model.param.CarModelSiteParam;
import com.yungu.swift.assets.driver.model.param.AdminCarModelSortParam;
import com.yungu.swift.assets.driver.model.param.CarModelWayParam;
import com.yungu.swift.assets.driver.service.CarModelService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.mapper.IMapper;
import com.yungu.swift.base.service.impl.BaseServiceImpl;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.system.sys.model.dto.SysCityDto;
import com.yungu.swift.utils.DateUtils;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 车型业务逻辑接口实现类
 *
 * @author cuixiuyin - Generate
 * @version 1.1.1-SNAPSHOT
 * @since 2018-07-02 11:19
 */
@Service
public class CarModelServiceImpl extends BaseServiceImpl<CarModelDto> implements CarModelService {
    @Autowired
    private CarModelMapper carModelMapper;
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private CarModelValuationMapper carValuationMapper;
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Override
    protected IMapper<CarModelDto> getMapper() {
        return carModelMapper;
    }

    @Override
    public ResponseData<Boolean> setDefault(Integer type, String uuid) {
        Boolean execute = transactionTemplate.execute(transactionStatus -> {
            // 设置同类型的车型为非默认值
            int setNotDefault = carModelMapper.setDefault(null, type, 0);
            // 设置选中的车型为默认车型
            int setDefault = carModelMapper.setDefault(uuid, null, 1);
            return setNotDefault > 0 && setDefault > 0;
        });
        if (execute) {
            return ResponseData.buildSuccessResponse("设置默认车型成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "设置默认车型失败");
    }

    @Override
    public ResponseData<Boolean> saveOrUpdate(CarModelDto carModelDto, String userUuid) {
        if (StringUtils.isEmpty(carModelDto.getUuid())) {
            carModelDto.setUuid(StringUtils.buildUUID());
            carModelDto.setStatus(1);
            carModelDto.setCreateOn(new Date());
            carModelDto.setCreateBy(userUuid);
            // 查询出同类型的车型的数量
            int count = carModelMapper.count(MapUtils.build("businessType", carModelDto.getBusinessType()));
            carModelDto.setSort(count + 1);
            carModelDto.setDefaultLevel(0);
            if (carModelMapper.add(carModelDto) == 0) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "新增车型失败");
            }
            // 新增车型的话 需要同步新增对应的计价规则
            Integer businessType = carModelDto.getBusinessType();
            List<SysCityDto> sysCityDtos = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(sysCityDtos)) {
                List<CarModelValuationDto> carModelValuationdtoList = new ArrayList<>();
                for (SysCityDto sysCityDto : sysCityDtos) {
                    //实时计费规则
                    CarModelValuationDto carModelsLevelRealDto = setCarModelsLevelDto(carModelDto, sysCityDto, CommonConstant.TYPE_TIME_REAL_TIME);
                    //预约计费规则
                    CarModelValuationDto carModelsLevelAppointDto = setCarModelsLevelDto(carModelDto, sysCityDto, CommonConstant.TYPE_TIME_APPIONT);
                    carModelValuationdtoList.add(carModelsLevelRealDto);
                    carModelValuationdtoList.add(carModelsLevelAppointDto);
                    //专车/快车业务的 日租/半日租
                    if (businessType == CommonConstant.BUSINESS_TYPE_SPEC || businessType == CommonConstant.BUSINESS_TYPE_EXPRESS) {
                        //新增半日租计费规则
                        CarModelValuationDto carModelsLevelDailyRentalDto = setCarModelsLevelDto(carModelDto, sysCityDto, CommonConstant.TYPE_TIME_DAILY_RENTAL);
                        //新增日租计费规则
                        CarModelValuationDto carModelsLevelHalfDailyRentalDto = setCarModelsLevelDto(carModelDto, sysCityDto, CommonConstant.TYPE_TIME_HALF_DAILY_RENTAL);
                        carModelValuationdtoList.add(carModelsLevelDailyRentalDto);
                        carModelValuationdtoList.add(carModelsLevelHalfDailyRentalDto);
                    }

                    // 专车/快车业务的 接送机服务
                    if (businessType == CommonConstant.BUSINESS_TYPE_SPEC || businessType == CommonConstant.BUSINESS_TYPE_EXPRESS) {
                        //接机计价规则
                        CarModelValuationDto carModelsLevelReceptionDto = setCarModelsLevelDto(carModelDto, sysCityDto, CommonConstant.TYPE_TIME_SEND_AIRPORT);
                        carModelValuationdtoList.add(carModelsLevelReceptionDto);
                        //接机计价规则
                        CarModelValuationDto meetAirport = setCarModelsLevelDto(carModelDto, sysCityDto, CommonConstant.TYPE_TIME_MEET_AIRPORT);
                        carModelValuationdtoList.add(meetAirport);
                    }
                }
                if (!carModelValuationdtoList.isEmpty()) {
                    carValuationMapper.addBatch(carModelValuationdtoList);
                }
            }
            return ResponseData.buildSuccessResponse("新增车型成功", Boolean.TRUE);
        }

        if (StringUtils.isNotEmpty(carModelDto.getUuid())) {
            carModelDto.setUpdateBy(userUuid);
            carModelDto.setUpdateOn(new Date());
            if (carModelMapper.edit(carModelDto) > 0) {
                return ResponseData.buildSuccessResponse("更新车型成功", Boolean.TRUE);
            }
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "更新车型失败");
    }

    /**
     * 获取运价码编号
     *
     * @param cityID
     * @param typeTrip
     * @param typeTime
     * @param sort
     * @return
     * @Description 规则：FT + 城市编码 + 业务编码 + 排序 + 订单时效性；共14位 ）
     * @author Zerrion
     */
    private String getFareType(String cityID, Integer typeTrip, int typeTime, int sort) {
        StringBuffer fareType = new StringBuffer();
        fareType.append("FT");
        fareType.append(cityID);
        //处理typeTrip，如果一位则补0，二位则不补0
        if (typeTrip < 10) {
            fareType.append("0");
            fareType.append(typeTrip.toString());
        } else {
            fareType.append(typeTrip.toString());
        }
        //排序处理
        //处理modelType，如果一位则补0，二位则不补0
        if (sort < 10) {
            fareType.append("0");
            fareType.append(sort);
        } else {
            fareType.append(sort);
        }
        //typeTime，如果一位则补0，二位则不补0
        if (typeTime < 10) {
            fareType.append("0");
            fareType.append(typeTime);
        } else {
            fareType.append(typeTime);
        }
        return fareType.toString();
    }

    @Override
    public ResponseData<Boolean> updateSort(AdminCarModelSortParam carModelSortParam) {
        List<AdminCarModelSortParam.CarModelSortParam> sortParams = carModelSortParam.getCarModelSortParams();
        List<Map> list = sortParams.stream().map(sortParam -> BeanMap.create(sortParam)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(sortParams) && carModelMapper.updateSort(list) == 0) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "更新排序失败");
        }
        return ResponseData.buildSuccessResponse("更新排序成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> delete(String uuid) {
        // 删除车型和计价规则之前 需要判断是否有车辆绑定该车型
        int count = carMapper.count(MapUtils.build("carModelUuid", uuid));
        if (count > 0) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无法删除，尚有车辆绑定该车型");
        }
        int affectedRowCount = carModelMapper.deleteByUuid(uuid);
        if (affectedRowCount == 0) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "删除失败，找不到对应车型");
        }
        // 伪删除计价规则
        carValuationMapper.virtualDeleteModelsLevelByCarLevelUuid(uuid);
        return ResponseData.buildSuccessResponse("删除车型成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Integer> getMaxSeats(Map<String, Object> params) {
        return ResponseData.buildSuccessResponse(carModelMapper.getMaxSeats(params));
    }

    @Override
    public ResponseData<List<CarModelDto>> listCarModelByWay(CarModelWayParam carModelWayParam) {
        List<CarModelDto> levels = carModelMapper.listCarModelByWay(carModelWayParam);
        if (null != levels && !levels.isEmpty()) {
            return ResponseData.buildSuccessResponse("获取路线车型成功", levels);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取路线车型失败，未查询到相关数据");
    }

    @Override
    public ResponseData<List<CarModelDto>> listCarModelByPointSite(CarModelSiteParam siteParam) {
        List<CarModelDto> carModelDtos = carModelMapper.listCarModelByPointSite(siteParam);
        if (CollectionUtils.isNotEmpty(carModelDtos)) {
            return ResponseData.buildSuccessResponse("获取起终点车型成功", carModelDtos);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取车型失败，未查询到相关数据");
    }

    private CarModelValuationDto setCarModelsLevelDto(CarModelDto carModelDto, SysCityDto sysCityDto, int typeTime) {
        CarModelValuationDto carModelValuationdto = new CarModelValuationDto();
        carModelValuationdto.setUuid(StringUtils.buildUUID());
        carModelValuationdto.setCityUuid(sysCityDto.getUuid());
        carModelValuationdto.setCarModelUuid(carModelDto.getUuid());
        carModelValuationdto.setOrderTypeTime(typeTime);
        //指定司机费用
        carModelValuationdto.setAssignDriverFare(0d);
        carModelValuationdto.setOwnCancelFare(0d);
        carModelValuationdto.setSysCancelFare(0d);
        //1高峰溢价倍率
        carModelValuationdto.setPremiumOneRate(1d);
        //1高峰时段
        carModelValuationdto.setPremiumOneStart(DateUtils.parse("07:00:00", "HH:MM:SS"));
        carModelValuationdto.setPremiumOneEnd(DateUtils.parse("09:00:00", "HH:MM:SS"));
        carModelValuationdto.setPremiumTwoRate(1d);
        carModelValuationdto.setPremiumTwoStart(DateUtils.parse("17:00:00", "HH:MM:SS"));
        carModelValuationdto.setPremiumTwoEnd(DateUtils.parse("19:00:00", "HH:MM:SS"));
        //起步价
        carModelValuationdto.setStartFare(10d);
        carModelValuationdto.setStartTrip(10d);
        carModelValuationdto.setStartDuration(30);
        //超出里程价格(元/公里)
        carModelValuationdto.setBeyondTripFare(3d);
        carModelValuationdto.setBeyondTimeFare(3d);
        //免费等待时间（超过这个时间才生效）
        carModelValuationdto.setFreeWaitTime(5);
        //超出等待时长费用（元/分钟）
        carModelValuationdto.setBeyondWaitFare(2d);
        //夜间开始时段
        carModelValuationdto.setNightTimeStart(DateUtils.parse("23:00:00", "HH:MM:SS"));
        carModelValuationdto.setNightTimeEnd(DateUtils.parse("06:00:00", "HH:MM:SS"));
        //夜间里程费（元/公里）
        carModelValuationdto.setNightTripFare(5d);
        //远途里程（超过这个里程才生效）
        carModelValuationdto.setHaulBackTrip(20d);
        //远途里程费用（元/公里）
        carModelValuationdto.setHaulBackTripFare(4d);
        //启用
        carModelValuationdto.setStatus(1);
        carModelValuationdto.setAppid(carModelDto.getAppid());
        carModelValuationdto.setCreateOn(new Date());
        carModelValuationdto.setFareType(getFareType(sysCityDto.getCityID(), carModelDto.getBusinessType(), typeTime, carModelDto.getSort()));
        return carModelValuationdto;
    }

    @Cached(name = "jetCache:assets:getCarModel:",key = "#uuid",expire = 300)
    @Override
    public ResponseData<CarModelDto> get(String uuid) {
        return get(MapUtils.build("uuid", uuid));
    }
}